package com.ld.data.utils;

import cn.hutool.core.text.StrPool;
import com.ld.data.business.file.vo.FileRespVo;
import com.ld.data.properties.LDProperties;
import io.minio.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

@Slf4j
@Component
public class MinioUtils {

    @Autowired
    private MinioClient client;

    @Autowired
    private LDProperties ldProperties;

    @SneakyThrows
    public FileRespVo upLoadFile(String bucketName, String folderName, String fileName, MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new RuntimeException("文件不能为空");
        }
        if (ObjectUtils.isEmpty(fileName)) {
            fileName = CommonUtils.getUUID();
        }
        String suffix = getFileExtension(file.getOriginalFilename());
        try {
            String defaultFolder = ldProperties.getMinio().getDefaultFolder();
            if (ObjectUtils.isEmpty(bucketName)) {
                bucketName = ldProperties.getMinio().getBucketName();
            }
            if (ObjectUtils.isEmpty(folderName)) {
                folderName = defaultFolder;
            }
            String fullName = getFilePath(folderName, fileName, suffix);
            String fileUrl = upLoadFile(bucketName, fullName, file.getInputStream(), file.getContentType());
            FileRespVo fileRespVo = new FileRespVo();
            fileRespVo.setFileName(fileName);
            fileRespVo.setFileSuffix(suffix);
            fileRespVo.setFileUrl(fileUrl);
            return fileRespVo;
        } catch (Exception e) {
            log.error("minio upLoadFile Exception:{}", e);
            throw new RuntimeException("文件上传失败,请重新上传或联系管理员");
        }
    }


    /**
     * 上传文件
     *
     * @param bucketName
     * @param fullName
     * @param stream
     * @param contentType
     * @return
     */
    private String upLoadFile(String bucketName, String fullName, InputStream stream, String contentType) {
        if (!bucketExists(bucketName)) {
            log.info("minio bucketName is not creat");
            makeBucket(bucketName);
        }
        try {
            client.putObject(PutObjectArgs.builder().bucket(bucketName).object(fullName)
                    .stream(stream, stream.available(), -1).contentType(contentType).build());
            String domain = ldProperties.getMinio().getDomain();
            stream.close();
            String fileUrl = domain + StrPool.SLASH + bucketName + fullName;
            log.info("minio upLoadFile success, fileUrl:{}", fileUrl);
            return fileUrl;
        } catch (Exception e) {
            log.error("uploadFile error:", e);
        }
        return null;
    }

    private String getFilePath(String folderName, String originalFilename, String suffix) {
        return StrPool.SLASH + String.join(StrPool.SLASH, folderName,
                originalFilename) + StrPool.C_UNDERLINE + DateUtils.currentTimeMillis() + StrPool.DOT + suffix;
    }

    /**
     * 判断空间是否存在
     *
     * @param bucketName
     * @return
     */
    public boolean bucketExists(String bucketName) {
        try {
            return client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error("minio bucketExists Exception:", e);
        }
        return false;
    }

    /**
     * 创建空间
     *
     * @param bucketName
     */
    public void makeBucket(String bucketName) {
        try {
            if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
                client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                log.info("minio makeBucket success bucketName:{}", bucketName);
            }
        } catch (Exception e) {
            log.error("minio makeBucket Exception:", e);
        }
    }

    /**
     * 获取文件后缀名
     *
     * @param fileName 文件全名
     * @return {String}
     */
    public static String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf('.');
        return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
    }


}
